﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;

using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolTip;

namespace DotNetUI.Controls.Shapes
{
    /// <summary>
    /// 圆弧
    /// </summary>
    public class Arc : Shape
    {
        /// <summary>
        /// 定义的集合图形
        /// </summary>
        protected override Geometry DefiningGeometry => this.Data;
        /// <summary>
        /// 设置值
        /// </summary>
        public Geometry Data { get => this.GetValue<Geometry>(DataProperty); set => this.SetValue(DataProperty, value); }
        /// <summary>
        /// 数据属性
        /// </summary>
        public static readonly DependencyProperty DataProperty = DependencyProperty.Register(nameof(Data), typeof(Geometry), typeof(Arc), new PropertyMetadata(Geometry.Empty, (s, e) =>
        {
            if (s is Arc arc && e.NewValue?.ToString() != e.OldValue?.ToString())
            {
                arc.InvalidateVisual();
            }
        }));
        /// <summary>
        /// 位置信息，大小信息
        /// </summary>
        public Rect Rect
        {
            get
            {
                var c = (Margin.Left + Margin.Right) / 2;
                var w = this.ActualWidth- (Margin.Left + Margin.Right);
                if (w<0)
                {
                    w = 0;
                }
                var c1 = (this.Margin.Top + this.Margin.Bottom) / 2;
                var h = this.ActualHeight- (this.Margin.Top + this.Margin.Bottom);
                if (h < 0)
                {
                    h = 0;
                }
                return new Rect(Margin.Left==double.NaN?0:Margin.Left,Margin.Right == double.NaN ? 0 : Margin.Right, w ,h );
            }
        }
        /// <summary>
        /// 起始角度
        /// </summary>
        public double StartAngle { get => this.GetValue<double>(StartAngleProperty); set => SetValue(StartAngleProperty, value); }
        /// <summary>
        /// 开始角度
        /// </summary>
        public static readonly DependencyProperty StartAngleProperty = DependencyProperty.Register(nameof(StartAngle), typeof(double), typeof(Arc), new PropertyMetadata(0.0D, OnAngleChangedCallBack));
        /// <summary>
        /// 结束角度
        /// </summary>
        public static readonly DependencyProperty EndAngleProperty = DependencyProperty.Register(nameof(EndAngle), typeof(double), typeof(Arc), new PropertyMetadata(0.0D, OnAngleChangedCallBack));
        /// <summary>
        /// 结束角度
        /// </summary>
        public double EndAngle { get => this.GetValue<double>(EndAngleProperty); set => SetValue(EndAngleProperty, value); }
        /// <summary>
        /// 是否关闭
        /// </summary>
        public static readonly DependencyProperty IsCloseProperty = DependencyProperty.Register(nameof(IsClose), typeof(bool), typeof(Arc), new PropertyMetadata(false, OnAngleChangedCallBack));
        /// <summary>
        /// 是否关闭
        /// </summary>
        public bool IsClose { get => this.GetValue<bool>(IsCloseProperty); set => SetValue(IsCloseProperty, value); }
        /// <summary>
        /// 角度修改回调
        /// </summary>
        /// <param name="dependencyObject"></param>
        /// <param name="dependencyPropertyChangedEventArgs"></param>
        protected static void OnAngleChangedCallBack(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
        {
            if (dependencyObject is Arc arc)
            {
                arc.OnAngleChanged();
            }
        }
        protected virtual void OnAngleChanged()
        {
            if (this.Rect.Width > 0 && this.Rect.Height > 0 && this.StartAngle != EndAngle)
            {
                var data = GetLine(this.Rect, StartAngle, EndAngle, IsClose);
                Data = data;
            }
            else
            {
                Data = Geometry.Empty;
            }
        }
        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            OnAngleChanged();
            base.OnRenderSizeChanged(sizeInfo);
        }
        protected Geometry GetLine(Rect rect, double startAngle, double endAngle, bool useClose)
        {
            double rx = rect.Width / 2;
            double ry = rect.Height / 2;
            if (Math.Abs(startAngle - endAngle) % 360 == 0)
            {
                EllipseGeometry pathGeometry = new EllipseGeometry()
                { Center = new Point { X = rect.X + rx, Y = rect.Y + ry }, RadiusX = rx, RadiusY = ry };
                return pathGeometry;
            }
            else
            {
                var clockWise = endAngle > startAngle;
                var majorArc = Math.Abs(startAngle - endAngle) % 360 >= 180;
                Point p1 = startAngle.GetPoint(rx, ry);
                Point p2 = endAngle.GetPoint(rx, ry);
                PathGeometry pathGeometry = new PathGeometry();
                var startPoint = new Point { X = p1.X + rx + Rect.X, Y = p1.Y + ry + Rect.Y };
                var endPoint = new Point { X = p2.X + rx + Rect.X, Y = p2.Y + ry + Rect.Y };
                var path = new PathFigure { StartPoint = startPoint, IsClosed = useClose };
                path.Segments.Add(new ArcSegment { Size = new Size() { Height = ry, Width = rx }, IsLargeArc = majorArc, SweepDirection = clockWise ? SweepDirection.Clockwise : SweepDirection.Counterclockwise, Point = endPoint });
                pathGeometry.Figures.Add(path);

                return pathGeometry;
            }

        }

    }
}
